<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>组件</title>
</head>
<body>
    <div id="app">
        <p>components: </p>
        <button-counter :prefix="123" @change-count="changeCount"/>
    </div>
    <script type="module">
        import { createApp, ref } from 'https://lib.baomitu.com/vue/3.2.31/vue.esm-browser.js'
        // // 1. prop 默认是可选的, 除非声明了 `required: true`
        // // 2. 未传递的 prop 会有一个缺省值 `undefined`
        // // 3. 如果声明了 defualt 值, 那么 prop 值会被解析成 undefined 值, 无论 prop 是未被传递还是显式指明的 undefined, 都会改为 default 值
        // defineProps({
        //     // 类型检查
        //     // 1. 给出 null 或者 undefined 值则会跳过任何类型检查
        //     propA: Number,
        //     propB: String,
        //     propC: Boolean,
        //     propD: Array,
        //     propE: Object,
        //     propF: Date,
        //     propG: Function,
        //     propH: Symbol,
        //     // 2. 多种类型
        //     propI: [String, Number],
        //     // 3. 必传, 且为 String 类型
        //     propJ: {
        //         type: String,
        //         required: true
        //     },
        //     // 4. 指定默认值, 如果不传则使用默认值
        //     propK: {
        //         type: Number,
        //         default: 100
        //     },
        //     // 默认值是工厂函数, 如果类型是 对象 或者 数组
        //     propL: {
        //         type: Object,
        //         default() {
        //             return {
        //                 message: 'hello'
        //             }
        //         }
        //     },
        //     // 5. 自定义校验函数
        //     propM: {
        //         validator(value) {
        //             return ['success', 'warning', 'danger'].includes(value)
        //         }
        //     },
        //     // 6. 函数类型的默认值
        //     propN: {
        //         type: Function,
        //         // 不像对象或数组的默认, 这不是一个工厂函数, 这是一个用来作为默认值的函数
        //         default() {
        //             return 'Default function'
        //         }
        //     }
        // })
        // 导入组件
        const ButtonCounter = {
            props: ['prefix'],
            emits: ['changeCount'],
            setup(props, ctx) {
                console.log('setup child: ', props, ctx)
                const count = ref(0)
                function increment() {
                    count.value++
                    ctx.emit('changeCount', 'fromChildfromChild')
                }
                return {
                    count,
                    increment
                }
            },
            template: `<button @click="increment">{{ prefix }} count is {{ count }}</button>`
        }
        const app = createApp({
            components: {
                ButtonCounter
            },
            setup() {
                function changeCount(fromChild) {
                    console.log('changeCount: ', fromChild)
                }
                return {
                    changeCount
                }
            }
        })
        // app.component('ButtonCounter', ButtonCounter)
        app.mount('#app')
    </script>

    <div id="app2">
        <child @some-event="someEvent" :parentdata="pd"></child>
    </div>
    <script type="module">
        import { createApp, ref } from 'https://lib.baomitu.com/vue/3.2.31/vue.esm-browser.js'
        const child = {
            props: ['parentdata'],
            emits: ['someEvent'],
            setup() {
                // 通过 $emit 触发自定义事件, 来将子组件想要传给父组件的数据
                const childData = ref('data from child')
                return {
                    childData
                }
            },
            template: `
                <div>
                    <p>{{ parentdata }}</p>
                    <button @click="$emit('someEvent', $event, childData)">click me</button>
                </div>
            `
        }
        const app = createApp({
            setup() {
                
                const pd = ref('data from parent')

                function someEvent(e, childData) {
                    console.log('someEvent: ', e, childData)
                }
                return {
                    pd,
                    someEvent
                }
            },
            components: {
                child
            }
        })
        app.mount('#app2')
    </script>

    <div id="app3">
        <child data="哈哈哈" @click="onChildClick"></child>
    </div>
    <script type="module">
        import { createApp, ref } from 'https://lib.baomitu.com/vue/3.2.31/vue.esm-browser.js'
        const child = {
            props: ['data'],
            emits: {
                // 没有校验
                // click: null
                click: ({ email, password }) => {
                    console.log(email, password)
                    if(email && password) {
                        return true 
                    } else {
                        alert('hhhh')
                        return false
                    }
                }
            },
            template: `
                <button @click="$emit('click', { email: '12', password: '123'})">{{ data }}</button>
            `
        }
        const app = createApp({
            components: {
                child
            },
            setup() {
                function onChildClick() {
                    console.log('onChildClick')
                }
                return {
                    onChildClick
                }
            }
        })
        app.mount('#app3')
    </script>

    <!-- v-model使用 -->
    <div id="app4">
        <p>{{ mInput }}</p>

        <!-- 这两种方式相同 -->
        <!-- <input v-model="mInput" /> -->
        <!-- <input type="text" :value="mInput" @input="mInput = $event.target.value"> -->
    </div>
    <script type="module">
        import { createApp, ref } from 'https://lib.baomitu.com/vue/3.2.31/vue.esm-browser.js'
        const app = createApp({
            setup() {
                const mInput = ref('')
                return {
                    mInput
                }
            }
        })
        app.mount('#app4')
    </script>

    <div id="app5">
        <p>父组件中: {{modelValue}}</p>
        <!-- <child :text="text" @update:text="value => text=value"></child> -->
        <child v-model="modelValue"></child>
    </div>
    <script type="module">
        import { createApp, ref } from 'https://lib.baomitu.com/vue/3.2.31/vue.esm-browser.js'
        const child = {
            props: ['modelValue'],
            emits: ['update:modelValue'],
            template: `
                <div>
                    {{modelValue}}
                    <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"/>
                </div>
            `
        }
        const app = createApp({
            components: {
                child
            },  
            setup() {
                const modelValue = ref('1234')
                console.log(modelValue)
                return {
                    modelValue
                }
            }
        })
        app.mount('#app5')
    </script>

    <div id="app6">
        <p>父组件中: {{modelValue}}</p>
        <child v-model.cap="modelValue"></child>
    </div>
    <script type="module">
        import { createApp, ref } from 'https://lib.baomitu.com/vue/3.2.31/vue.esm-browser.js'
        const child = {
            // props: ['modelValue'],
            // modelModifiers 处理自定义修饰符
            props: {
                modelValue: String,
                modelModifiers: {
                    default: () => ({})
                }
            },
            emits: ['update:modelValue'],
            created() {
                console.log(this.modelModifiers)
            },
            computed: {
                value: {
                    get() {
                        return this.modelValue
                    },
                    set(val) {
                        this.$emit('update:modelValue', val)
                    }
                }
            },
            template: `
                <div>
                    {{modelValue}}
                    <input v-model="value"/>
                </div>
            `
            // <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"/>
        }
        const app = createApp({
            components: {
                child
            },
            setup() {
                const modelValue = ref('data from parent')
                return {
                    modelValue
                }
            }
        })
        app.mount('#app6')
    </script>
</body>
</html>